package nl.haemers.data.reflection 
{
	import flash.errors.IllegalOperationError;
	import flash.utils.describeType;
	import flash.utils.getDefinitionByName;
	import nl.haemers.data.serializers.ObjectSerializer;
	import nl.haemers.data.constants.ReflectionConstants;
	/**
	 * ...
	 * @author Jonathan Haemers
	 */
	// TODO: check for parameters in the constructor.
	// TODO: check for methods in the class.
	public class Type
	{
		private var _class				:Class;
		
		private var _name				:String;
		private var _base				:String;
		private var _extends			:String;
		
		private var _isDynamic			:Boolean;
		private var _isFinal			:Boolean;
		private var _isStatic			:Boolean;
		
		private var _isTypedCollection	:Boolean;
		private var _collectionType		:Type;
		
		private var _accessors			:IAccessors;
		private var _variables			:*;
		private var _metadatas			:IMetadatas;
		
		//This wil be some kind of treenode
		private var _level				:int;
		
		//if it's a Vector you have a Factory layer
		private var _factory			:Boolean;	
		
		public function Type(currentLevel:int) 
		{
			_level = currentLevel;
		}
		
		/** Public methods **/
		public function init(ClassReference:Class) : void
		{
			var _instance:Object = new ClassReference();
			if (_instance == null)
			{
				throw new IllegalOperationError("This isn't a legal ClassReference.");
			}
			var xml:XML = describeType(_instance);
			trace(xml);
			this._class = ClassReference;
			
			this._metadatas = Metadatas.init(xml);
			var serialize:IMetadata = this._metadatas.getMetadata(ReflectionConstants.OBJECT_ATTRIBUTE)
			this._name = serialize != null ? serialize.args.getArg(ReflectionConstants.ATTRIBUTE_NAME).value : xml.@name;
			
			this._base = xml.@base;
			this._isDynamic = xml.@isDynamic == "true";
			this._isFinal = xml.@isFinal == "true";
			this._isStatic = xml.@isStatic == "true";
			
			//this._extends = this.getExtensions(xml);
			//TODO: Not sure what to do with the factory layer for know just leave it...
			this._factory = xml.contains("factory");
			if (this._factory)
			{
				this._accessors = Accessors.init(xml.elements("factory"));
			}
			else
			{
				this._accessors = Accessors.init(xml);
			}
			
			if (this._name.indexOf("__AS3__.vec::Vector.") === 0)
			{
				var vectorRegExp:RegExp = /[.*]<(.*)>[.*]?/i;
				var result:Object = vectorRegExp.exec(this._name);
				
				if (result)
				{
					trace("result: " + result);
					trace("Found result: " + result[1]);
					var typedObject:Class = getDefinitionByName(result[1]) as Class;
					this._collectionType = ObjectSerializer.getType(typedObject);
					this._isTypedCollection = true;
					trace(typedObject);
				}
			}
			//this._os = ObjectSerializer.
			//create extensions
			//create metadata
				//metadata create args
			//create accessors
				//accessors create metadata
					//metadata create args
				//Accessors CHECK for type custom objects if true
					//accessors create Type
						//Type create above
			//create variables
				//variables create metadata
					//metadata create args
				//Variables CHECK for type custom objects if true
					//variables create Type
			
			//create Factories this means we are in a Vector
				//Factory is sort of a extra layer between type and accessors, variables
		}
		
		public function hasParent() : Boolean
		{
			return this._level > 0;
		}
		/** Getters & Setters **/
		public function get instance() : Object
		{
			return new _class();
		}
		
		public function get collectionType() : Type
		{ 
			return _collectionType;
		}
		/*
		public function get collectionInstance() : Object
		{
			return this._isTypedCollection ? this._collectionType.instance : null;
		}
		*/
		public function get name() : String
		{
			return _name;
		}
		public function get base() : String
		{
			return _base;
		}
		public function get isDynamic() : Boolean
		{
			return _isDynamic;
		}
		public function get isFinal() : Boolean
		{
			return _isFinal;
		}
		public function get isStatic() : Boolean
		{
			return _isStatic;
		}
		
		public function get metadatas() : IMetadatas
		{
			return _metadatas;
		}
		
		public function get accessors() : IAccessors
		{
			return _accessors;
		}
		/** Protected methods **/
		
		/** Private methods **/
		
		/*
		<type name="nl.haemers.test.data.vo::PageVO" base="Class" isDynamic="true" isFinal="true" isStatic="true">
		  <extendsClass type="Class"/>
		  <extendsClass type="Object"/>
		  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
		  <factory type="nl.haemers.test.data.vo::PageVO">
			<extendsClass type="Object"/>
			<accessor name="url" access="readwrite" type="String" declaredBy="nl.haemers.test.data.vo::PageVO">
			  <metadata name="Serialize">
				<arg key="name" value="page"/>
			  </metadata>
			  <metadata name="__go_to_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
				<arg key="pos" value="546"/>
			  </metadata>
			  <metadata name="__go_to_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
				<arg key="pos" value="611"/>
			  </metadata>
			</accessor>
			<accessor name="name" access="readwrite" type="String" declaredBy="nl.haemers.test.data.vo::PageVO">
			  <metadata name="__go_to_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
				<arg key="pos" value="368"/>
			  </metadata>
			  <metadata name="__go_to_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
				<arg key="pos" value="435"/>
			  </metadata>
			</accessor>
			<metadata name="Serialize">
			  <arg key="name" value="page"/>
			</metadata>
			<metadata name="__go_to_ctor_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
			  <arg key="pos" value="229"/>
			</metadata>
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\PageVO.as"/>
			  <arg key="pos" value="129"/>
			</metadata>
		  </factory>
		</type>
		*/
		
		/**
		 * <metadata name="Serialize">
				<arg key="name" value="environment"/>
			  </metadata>
			  <metadata name="__go_to_ctor_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\EnvironmentVO.as"/>
				<arg key="pos" value="657"/>
			  </metadata>
			  <metadata name="__go_to_definition_help">
				<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\EnvironmentVO.as"/>
				<arg key="pos" value="136"/>
			  </metadata>
		 * 
		 */
		
		
		/*
		<type name="nl.haemers.test.data.vo::TestVO" base="Object" isDynamic="false" isFinal="false" isStatic="false">
		  <extendsClass type="Object"/>
		   <variable name="street" type="String">
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="357"/>
			</metadata>
		  </variable>
		  <variable name="hometown" type="String">
			<metadata name="Serialize">
			  <arg key="name" value="city"/>
			</metadata>
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="422"/>
			</metadata>
		  </variable>
		  */
		  /*
		  <accessor name="addressVO" access="readwrite" type="nl.haemers.test.data.vo::AddressVO" declaredBy="nl.haemers.test.data.vo::TestVO">
			 <metadata name="Serialize">
			  <arg key="name" value="address"/>
			</metadata>
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="1522"/>
			</metadata>
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="1601"/>
			</metadata>
		  </accessor>
		  */
		  /*
		  <accessor name="id" access="readwrite" type="int" declaredBy="nl.haemers.test.data.vo::TestVO">
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="518"/>
			</metadata>
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="579"/>
			</metadata>
		  </accessor>
		  <accessor name="title" access="readwrite" type="String" declaredBy="nl.haemers.test.data.vo::TestVO">
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="411"/>
			</metadata>
			<metadata name="Serialize">
				<arg key="type" value="title"/>
			</metadata>
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="331"/>
			</metadata>
		  </accessor>
		  <accessor name="xPos" access="readwrite" type="Number" declaredBy="nl.haemers.test.data.vo::TestVO">
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="657"/>
			</metadata>
			<metadata name="__go_to_definition_help">
			  <arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			  <arg key="pos" value="725"/>
			</metadata>
		  </accessor>
		  <metadata name="__go_to_ctor_definition_help">
			<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			<arg key="pos" value="227"/>
		  </metadata>
		  <metadata name="__go_to_definition_help">
			<arg key="file" value="D:\work\asjlib\trunk\src\nl\haemers\test\data\vo\TestVO.as"/>
			<arg key="pos" value="93"/>
		  </metadata>
		</type>
		*/
	}

}